package com.jirefox.loner.runtime.service;

import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import javax.annotation.PostConstruct;

import org.apache.catalina.Host;
import org.apache.catalina.Wrapper;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.startup.Tomcat.FixContextListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.embedded.tomcat.TomcatWebServer;
import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext;
import org.springframework.stereotype.Service;

import com.jirefox.loner.runtime.model.DriverGroup;
import com.jirefox.loner.runtime.model.ExtClassDriverServlet;

@Service
public class JdbcDriverService {

	private final Logger logger = LoggerFactory.getLogger(JdbcDriverService.class);

	@Value("${loner.driversDir:#{null}}")
	private String driversDir;

	@Autowired
	ServletWebServerApplicationContext servletWebServerApplicationContext;

	private final Map<String, DriverGroup> store = new HashMap<String, DriverGroup>();

	@PostConstruct
	public void init() throws Exception {
		if (driversDir == null) {
			return;
		}
		File driversFolder = new File(driversDir);
		if (!driversFolder.exists()) {
			driversFolder.mkdirs();
		}

		for (File driverFileFolder : driversFolder.listFiles()) {
			logger.info("registerDriverClassLoader from {}", driverFileFolder.getAbsolutePath());
			registerDriverClassLoader(driverFileFolder);
		}

	}

	public DriverGroup getDriverGroup(String driverGroupName) {
		DriverGroup driverGroup = store.get(driverGroupName);
		return driverGroup;
	}

	public void registerDriverClassLoader(File driverFolder) {

		StandardContext context = new StandardContext();
		String driverFolderName = driverFolder.getName();
		context.setName(driverFolderName);
		context.setDisplayName(driverFolderName);

		String contextPath = "/" + UUID.randomUUID().toString();
		context.setPath(contextPath);
		context.setCrossContext(true);
		context.setDocBase(driverFolder.getAbsolutePath());
		context.addLifecycleListener(new FixContextListener());

		Wrapper driverServlet = context.createWrapper();
		driverServlet.setName(driverFolderName);
		driverServlet.setServletClass(ExtClassDriverServlet.class.getName());
		driverServlet.setLoadOnStartup(1);
		driverServlet.setOverridable(true);

		context.setParentClassLoader(Thread.currentThread().getContextClassLoader());

		context.addChild(driverServlet);

		TomcatWebServer webServer = (TomcatWebServer) servletWebServerApplicationContext.getWebServer();
		Host host = webServer.getTomcat().getHost();
		host.addChild(context);

		ClassLoader driverClassLoader = (ClassLoader) context.getServletContext()
				.getAttribute(ExtClassDriverServlet.DRIVER_GROUP_CLASSLOADER_KEY);

		DriverGroup driverGroup = new DriverGroup();

		String driverGroupName = driverFolder.getName();
		driverGroup.setName(driverGroupName);
		driverGroup.setClassLoader(driverClassLoader);

		// TODO scan driver names from jar

		store.put(driverGroup.getName(), driverGroup);
	}

}
